home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xmcd-1.4 / libdi.d / vu_sony.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  14.0 KB  |  664 lines

  1. /*
  2.  *   libdi - CD Audio Player Device Interface Library
  3.  *
  4.  *   Copyright (C) 1995  Ti Kan
  5.  *   E-mail: ti@amb.org
  6.  *
  7.  *   This program is free software; you can redistribute it and/or modify
  8.  *   it under the terms of the GNU General Public License as published by
  9.  *   the Free Software Foundation; either version 2 of the License, or
  10.  *   (at your option) any later version.
  11.  *
  12.  *   This program is distributed in the hope that it will be useful,
  13.  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *   GNU General Public License for more details.
  16.  *
  17.  *   You should have received a copy of the GNU General Public License
  18.  *   along with this program; if not, write to the Free Software
  19.  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *   The name "Sony" is a trademark of Sony Corporation, and is used
  22.  *   here for identification purposes only.  This software and its
  23.  *   author are not affiliated in any way with Sony.
  24.  *
  25.  */
  26. #ifndef LINT
  27. static char *_vu_sony_c_ident_ = "@(#)vu_sony.c    5.4 94/12/28";
  28. #endif
  29.  
  30. #include "common.d/appenv.h"
  31. #include "common.d/util.h"
  32. #include "libdi.d/libdi.h"
  33. #include "libdi.d/scsipt.h"
  34.  
  35. #ifdef VENDOR_SONY
  36.  
  37. extern appdata_t    app_data;
  38. extern vu_tbl_t        scsipt_vutbl[];
  39.  
  40. STATIC byte_t        sony_route_left,    /* left ch routing control */
  41.             sony_route_right;    /* Right ch routing control */
  42.  
  43.  
  44. /*
  45.  * sony_route_val
  46.  *    Return the channel routing control value used in the
  47.  *    Sony Playback Status command.
  48.  *
  49.  * Args:
  50.  *    route_mode - The channel routing mode value.
  51.  *    channel - The channel number desired (0=left 1=right).
  52.  *
  53.  * Return:
  54.  *    The routing control value.
  55.  */
  56. STATIC byte_t
  57. sony_route_val(int route_mode, int channel)
  58. {
  59.     switch (channel) {
  60.     case 0:
  61.         switch (route_mode) {
  62.         case 0:
  63.             return 0x1;
  64.             break;
  65.         case 1:
  66.             return 0x2;
  67.             break;
  68.         case 2:
  69.             return 0x1;
  70.             break;
  71.         case 3:
  72.             return 0x2;
  73.             break;
  74.         case 4:
  75.             return 0x3;
  76.             break;
  77.         default:
  78.             /* Invalid value */
  79.             return 0x0;
  80.             break;
  81.         }
  82.         break;
  83.  
  84.     case 1:
  85.         switch (route_mode) {
  86.         case 0:
  87.             return 0x2;
  88.             break;
  89.         case 1:
  90.             return 0x1;
  91.             break;
  92.         case 2:
  93.             return 0x1;
  94.             break;
  95.         case 3:
  96.             return 0x2;
  97.             break;
  98.         case 4:
  99.             return 0x3;
  100.             break;
  101.         default:
  102.             /* Invalid value */
  103.             return 0x0;
  104.             break;
  105.         }
  106.         break;
  107.  
  108.     default:
  109.         /* Invalid value */
  110.         return 0x0;
  111.     }
  112. }
  113.  
  114.  
  115. /*
  116.  * sony_playaudio
  117.  *    Play audio function: send vendor-unique play audio command
  118.  *    to the drive.
  119.  *
  120.  * Args:
  121.  *    addr_fmt - Flags indicating which address formats are passed in
  122.  *    If ADDR_BLK, then:
  123.  *        start_addr - The logical block starting address
  124.  *        end_addr - The logical block ending address
  125.  *    If ADD_MSF, then:
  126.  *        start_msf - Pointer to the starting MSF address structure
  127.  *        end_msf - Pointer to the ending MSF address structure
  128.  *    If ADDR_TRKIDX, then:
  129.  *        trk - The starting track number
  130.  *        idx - The starting index number
  131.  *    If ADDR_OPTEND, then the ending address, if specified, can be
  132.  *    ignored if possible.
  133.  *
  134.  * Return:
  135.  *    TRUE - success
  136.  *    FALSE - failure
  137.  */
  138. /*ARGSUSED*/
  139. bool_t
  140. sony_playaudio(
  141.     byte_t        addr_fmt,
  142.     word32_t    start_addr,
  143.     word32_t    end_addr,
  144.     msf_t        *start_msf,
  145.     msf_t        *end_msf,
  146.     byte_t        trk,
  147.     byte_t        idx
  148. )
  149. {
  150.     msf_t        istart_msf,
  151.             iend_msf;
  152.     word32_t    *addr;
  153.     word16_t    *len;
  154.     byte_t        *rsvd;
  155.     curstat_t    *s = (curstat_t *) curstat_addr();
  156.     bool_t        ret = FALSE;
  157.  
  158.     if (!ret && (addr_fmt & ADDR_BLK) && !(addr_fmt & ADDR_MSF)) {
  159.         /* Convert block address to MSF format */
  160.         blktomsf(
  161.             start_addr,
  162.             &istart_msf.min, &istart_msf.sec, &istart_msf.frame,
  163.             MSF_OFFSET(s)
  164.         );
  165.  
  166.         blktomsf(
  167.             end_addr,
  168.             &iend_msf.min, &iend_msf.sec, &iend_msf.frame,
  169.             MSF_OFFSET(s)
  170.         );
  171.  
  172.         /* Let the ADDR_MSF code handle the request */
  173.         start_msf = &istart_msf;
  174.         end_msf = &iend_msf;
  175.         addr_fmt |= ADDR_MSF;
  176.         ret = FALSE;
  177.     }
  178.  
  179.     if (!ret && addr_fmt & ADDR_MSF) {
  180.         addr = (word32_t *)(void *) start_msf;
  181.         rsvd = (byte_t *) &end_msf->min;
  182.         len = (word16_t *)(void *) &end_msf->sec;
  183.  
  184.         ret = pthru_send(
  185.             OP_VS_PLAYMSF,
  186.             bswap32(*addr),
  187.             NULL,
  188.             0,
  189.             *rsvd,
  190.             (word32_t) bswap16(*len),
  191.             0,
  192.             0,
  193.             READ_OP,
  194.             TRUE
  195.         );
  196.             
  197.     }
  198.  
  199.     return (ret);
  200. }
  201.  
  202.  
  203. /*
  204.  * sony_pause_resume
  205.  *    Pause/resume function: send vendor-unique commands to implement
  206.  *    the pause and resume capability.
  207.  *
  208.  * Args:
  209.  *    resume - TRUE: resume, FALSE: pause
  210.  *
  211.  * Return:
  212.  *    TRUE - success
  213.  *    FALSE - failure
  214.  */
  215. bool_t
  216. sony_pause_resume(bool_t resume)
  217. {
  218.     if (resume) {
  219.         return (
  220.             pthru_send(
  221.                 OP_VS_PAUSE, 0, NULL, 0, 0, 0,
  222.                 0x0, 0, READ_OP, TRUE
  223.             )
  224.         );
  225.     }
  226.     else {
  227.         return (
  228.             pthru_send(
  229.                 OP_VS_PAUSE, 0, NULL, 0, 0, 0,
  230.                 0x1 << 4, 0, READ_OP, TRUE
  231.             )
  232.         );
  233.     }
  234. }
  235.  
  236.  
  237. /*
  238.  * sony_get_playstatus
  239.  *    Send vendor-unique command to obtain current audio playback
  240.  *    status.
  241.  *
  242.  * Args:
  243.  *    s - Pointer to the curstat_t structure
  244.  *    audio_status - Address where a current status code (SCSI-2
  245.  *               style) is to be returned.
  246.  *
  247.  * Return:
  248.  *    TRUE - success
  249.  *    FALSE - failure
  250.  */
  251. bool_t
  252. sony_get_playstatus(curstat_t *s, byte_t *audio_status)
  253. {
  254.     int        i,
  255.             trkno,
  256.             idxno;
  257.     byte_t        dbuf[sizeof(sstat_data_t)],
  258.             qbuf[sizeof(ssubq_data_t)];
  259.     sstat_data_t    *d;
  260.     ssubq_data_t    *q;
  261.  
  262.  
  263.     /*
  264.      * Send Sony Playback Status command
  265.      */
  266.  
  267.     memset(dbuf, 0, sizeof(dbuf));
  268.  
  269.     if (!pthru_send(OP_VS_PLAYSTAT, 0, dbuf, SZ_VS_PLAYSTAT, 0,
  270.             SZ_VS_PLAYSTAT, 0, 0, READ_OP, TRUE))
  271.         return FALSE;
  272.  
  273.     DBGDUMP("sony: Playback Status data bytes", dbuf, SZ_VS_PLAYSTAT);
  274.  
  275.     d = (sstat_data_t *)(void *) dbuf;
  276.  
  277.     /* Translate Sony audio status to SCSI-2 audio status */
  278.     switch (d->audio_status) {
  279.     case SAUD_PLAYING:
  280.     case SAUD_MUTED:
  281.         *audio_status = AUDIO_PLAYING;
  282.         break;
  283.  
  284.     case SAUD_PAUSED:
  285.         *audio_status = AUDIO_PAUSED;
  286.         break;
  287.  
  288.     case SAUD_COMPLETED:
  289.         *audio_status = AUDIO_COMPLETED;
  290.         break;
  291.  
  292.     case SAUD_ERROR:
  293.         *audio_status = AUDIO_FAILED;
  294.         break;
  295.  
  296.     case SAUD_NOTREQ:
  297.         *audio_status = AUDIO_NOSTATUS;
  298.         break;
  299.     }
  300.  
  301.     if ((i = curtrk_pos(s)) >= 0)
  302.         s->trkinfo[i].type = (d->trktype == 0) ? TYP_AUDIO : TYP_DATA;
  303.  
  304.  
  305.     /*
  306.      * Send Sony Read Subchannel command
  307.      */
  308.  
  309.     memset(qbuf, 0, sizeof(qbuf));
  310.  
  311.     if (!pthru_send(OP_VS_RDSUBQ, (word32_t) (1 << 30), qbuf,
  312.             SZ_VS_RDSUBQ, 0, SZ_VS_RDSUBQ, 0, 0, READ_OP, TRUE))
  313.         return FALSE;
  314.  
  315.     DBGDUMP("sony: Read Subchannel data bytes", qbuf, SZ_VS_RDSUBQ);
  316.  
  317.     q = (ssubq_data_t *)(void *) qbuf;
  318.  
  319.     trkno = (word32_t) q->trkno;
  320.     if (s->cur_trk != trkno) {
  321.         s->cur_trk = trkno;
  322.         dpy_track(s);
  323.     }
  324.  
  325.     idxno = (word32_t) q->idxno;
  326.     if (s->cur_idx != idxno) {
  327.         s->cur_idx = idxno;
  328.         s->sav_iaddr = s->cur_tot_addr;
  329.         dpy_index(s);
  330.     }
  331.  
  332.     s->cur_tot_min = (byte_t) q->abs_min;
  333.     s->cur_tot_sec = (byte_t) q->abs_sec;
  334.     s->cur_tot_frame = (byte_t) q->abs_frame;
  335.     s->cur_trk_min = (byte_t) q->rel_min;
  336.     s->cur_trk_sec = (byte_t) q->rel_sec;
  337.     s->cur_trk_frame = (byte_t) q->rel_frame;
  338.     msftoblk(
  339.         s->cur_tot_min, s->cur_tot_sec, s->cur_tot_frame,
  340.         &s->cur_tot_addr, MSF_OFFSET(s)
  341.     );
  342.     msftoblk(
  343.         s->cur_trk_min, s->cur_trk_sec, s->cur_trk_frame,
  344.         &s->cur_trk_addr, 0
  345.     );
  346.  
  347.     return TRUE;
  348. }
  349.  
  350.  
  351. /*
  352.  * sony_get_toc
  353.  *    Send vendor-unique command to obtain the disc table-of-contents
  354.  *
  355.  * Args:
  356.  *    s - Pointer to the curstat_t structure, which contains the TOC
  357.  *        table to be updated.
  358.  *
  359.  * Return:
  360.  *    TRUE - success
  361.  *    FALSE - failure
  362.  */
  363. bool_t
  364. sony_get_toc(curstat_t *s)
  365. {
  366.     int        i,
  367.             j,
  368.             xfer_len;
  369.     byte_t        buf[sizeof(stoc_data_t)];
  370.     stoc_data_t    *d;
  371.     stoc_ent_t    *e;
  372.  
  373.     memset(buf, 0, sizeof(buf));
  374.  
  375.     /* Read TOC header to find the number of tracks */
  376.     for (i = 1; i < MAXTRACK - 1; i++) {
  377.         if (pthru_send(OP_VS_RDTOC, i, buf, SZ_VS_TOCHDR,
  378.                    0, SZ_VS_TOCHDR, 0, 0, READ_OP, TRUE))
  379.             break;
  380.     }
  381.     if (i == MAXTRACK - 1)
  382.         return FALSE;
  383.  
  384.     d = (stoc_data_t *) buf;
  385.  
  386.     s->first_trk = (byte_t) d->first_trk;
  387.     s->last_trk = (byte_t) d->last_trk;
  388.  
  389.     xfer_len = SZ_VS_TOCHDR +
  390.            ((int) (d->last_trk - d->first_trk + 2) * SZ_VS_TOCENT);
  391.  
  392.     if (xfer_len > SZ_VS_RDTOC)
  393.         xfer_len = SZ_VS_RDTOC;
  394.  
  395.     if (pthru_send(OP_VS_RDTOC, (word32_t) s->first_trk,
  396.                buf, xfer_len, 0, xfer_len, 0, 0, READ_OP, TRUE))
  397.         return FALSE;
  398.  
  399.     DBGDUMP("sony: Read TOC data bytes", buf, SZ_VS_RDTOC);
  400.  
  401.     /* Get the starting position of each track */
  402.     for (i = 0, j = (int) s->first_trk; j <= (int) s->last_trk; i++, j++) {
  403.         e = (stoc_ent_t *)(void *) &d->trkdata[(i+1) * SZ_VS_TOCENT];
  404.         s->trkinfo[i].trkno = j;
  405.         s->trkinfo[i].min = (byte_t) e->min;
  406.         s->trkinfo[i].sec = (byte_t) e->sec;
  407.         s->trkinfo[i].frame = (byte_t) e->frame;
  408.         msftoblk(
  409.             s->trkinfo[i].min,
  410.             s->trkinfo[i].sec,
  411.             s->trkinfo[i].frame,
  412.             &s->trkinfo[i].addr,
  413.             MSF_OFFSET(s)
  414.         );
  415.         s->trkinfo[i].type = (e->trktype == 0) ? TYP_AUDIO : TYP_DATA;
  416.     }
  417.     s->tot_trks = (byte_t) i;
  418.  
  419.     /* Get the lead-out track position */
  420.     e = (stoc_ent_t *)(void *) &d->trkdata[0];
  421.     s->trkinfo[i].trkno = LEAD_OUT_TRACK;
  422.     s->tot_min = s->trkinfo[i].min = (byte_t) e->min;
  423.     s->tot_sec = s->trkinfo[i].sec = (byte_t) e->sec;
  424.     s->tot_frame = s->trkinfo[i].frame = (byte_t) e->frame;
  425.     msftoblk(
  426.         s->trkinfo[i].min,
  427.         s->trkinfo[i].sec,
  428.         s->trkinfo[i].frame,
  429.         &s->trkinfo[i].addr,
  430.         MSF_OFFSET(s)
  431.     );
  432.     s->tot_addr = s->trkinfo[i].addr;
  433.     return TRUE;
  434. }
  435.  
  436.  
  437. /*
  438.  * sony_volume
  439.  *    Send vendor-unique command to query/control the playback volume.
  440.  *
  441.  * Args:
  442.  *    vol - Volume level to set to
  443.  *    s - Pointer to the curstat_t structure
  444.  *    query - This call is to query the current volume setting rather
  445.  *        than to set it.
  446.  *
  447.  * Return:
  448.  *    The current volume value.
  449.  */
  450. int
  451. sony_volume(int vol, curstat_t *s, bool_t query)
  452. {
  453.     int        i,
  454.             vol1,
  455.             vol2;
  456.     byte_t        buf[sizeof(sstat_data_t)];
  457.     sstat_data_t    *d;
  458.  
  459.     memset(buf, 0, sizeof(buf));
  460.  
  461.     if (!pthru_send(OP_VS_PLAYSTAT, 0, buf, SZ_VS_PLAYSTAT, 0,
  462.             SZ_VS_PLAYSTAT, 0, 0, READ_OP, TRUE))
  463.         return -1;
  464.  
  465.     DBGDUMP("sony: Playback Status data bytes", buf, SZ_VS_PLAYSTAT);
  466.  
  467.     d = (sstat_data_t *)(void *) buf;
  468.  
  469.     if (query) {
  470.         vol1 = untaper_vol(unscale_vol((int) d->vol0));
  471.         vol2 = untaper_vol(unscale_vol((int) d->vol1));
  472.         sony_route_left = (byte_t) d->sel0;
  473.         sony_route_right = (byte_t) d->sel1;
  474.  
  475.         if (vol1 == vol2) {
  476.             s->level_left = s->level_right = 100;
  477.             vol = vol1;
  478.         }
  479.         else if (vol1 > vol2) {
  480.             s->level_left = 100;
  481.             s->level_right = (byte_t) ((vol2 * 100) / vol1);
  482.             vol = vol1;
  483.         }
  484.         else {
  485.             s->level_left = (byte_t) ((vol1 * 100) / vol2);
  486.             s->level_right = 100;
  487.             vol = vol2;
  488.         }
  489.  
  490.         return (vol);
  491.     }
  492.     else {
  493.         memset(buf, 0, 10);
  494.  
  495.         d->vol0 = (byte_t) scale_vol(
  496.             taper_vol(vol * (int) s->level_left / 100)
  497.         );
  498.         d->vol1 = (byte_t) scale_vol(
  499.             taper_vol(vol * (int) s->level_right / 100)
  500.         );
  501.         d->sel0 = sony_route_left;
  502.         d->sel1 = sony_route_right;
  503.  
  504.         DBGDUMP("sony: Playback Control data bytes",
  505.             buf, SZ_VS_PLAYSTAT);
  506.  
  507.         if (pthru_send(OP_VS_PLAYCTL, 0, buf, SZ_VS_PLAYSTAT, 0,
  508.                 SZ_VS_PLAYSTAT, 0, 0, WRITE_OP, TRUE)) {
  509.             /* Success */
  510.             return (vol);
  511.         }
  512.         else if (d->vol0 != d->vol1) {
  513.             /* Set the balance to the center
  514.              * and retry.
  515.              */
  516.             d->vol0 = d->vol1 = scale_vol(taper_vol(vol));
  517.  
  518.             DBGDUMP("sony: Playback Control data bytes",
  519.                 buf, SZ_VS_PLAYSTAT);
  520.  
  521.             if (pthru_send(OP_VS_PLAYCTL, 0, buf, SZ_VS_PLAYSTAT, 0,
  522.                     SZ_VS_PLAYSTAT, 0, 0, WRITE_OP, TRUE)) {
  523.                 /* Success: Warp balance control */
  524.                 s->level_left = s->level_right = 100;
  525.                 return (vol);
  526.             }
  527.  
  528.             /* Still failed: just drop through */
  529.         }
  530.     }
  531.  
  532.     return -1;
  533. }
  534.  
  535.  
  536. /*
  537.  * sony_route
  538.  *    Configure channel routing via Sony Vendor-unique commands.
  539.  *
  540.  * Args:
  541.  *    s - Pointer to the curstat_t structure
  542.  *
  543.  * Return:
  544.  *    TRUE - success
  545.  *    FALSE - failure
  546.  */
  547. bool_t
  548. sony_route(curstat_t *s)
  549. {
  550.     byte_t    val0,
  551.         val1;
  552.  
  553.     val0 = sony_route_val(app_data.ch_route, 0);
  554.     val1 = sony_route_val(app_data.ch_route, 1);
  555.  
  556.     if (val0 == sony_route_left && val1 == sony_route_right)
  557.         /* No change: just return */
  558.         return TRUE;
  559.  
  560.     sony_route_left = val0;
  561.     sony_route_right = val1;
  562.  
  563.     /* Sony channel routing is done with the volume control */
  564.     (void) sony_volume(s->level, s, FALSE);
  565.  
  566.     return TRUE;
  567. }
  568.  
  569.  
  570. /*
  571.  * sony_init
  572.  *    Initialize the vendor-unique support module
  573.  *
  574.  * Args:
  575.  *    Nothing.
  576.  *
  577.  * Return:
  578.  *    Nothing.
  579.  */
  580. void
  581. sony_init(void)
  582. {
  583.     /* Register vendor_unique module entry points */
  584.     scsipt_vutbl[VENDOR_SONY].vendor = "Sony";
  585.     scsipt_vutbl[VENDOR_SONY].playaudio = sony_playaudio;
  586.     scsipt_vutbl[VENDOR_SONY].pause_resume = sony_pause_resume;
  587.     scsipt_vutbl[VENDOR_SONY].start_stop = NULL;
  588.     scsipt_vutbl[VENDOR_SONY].get_playstatus = sony_get_playstatus;
  589.     scsipt_vutbl[VENDOR_SONY].volume = sony_volume;
  590.     scsipt_vutbl[VENDOR_SONY].route = sony_route;
  591.     scsipt_vutbl[VENDOR_SONY].mute = NULL;
  592.     scsipt_vutbl[VENDOR_SONY].get_toc = sony_get_toc;
  593.     scsipt_vutbl[VENDOR_SONY].eject = NULL;
  594.     scsipt_vutbl[VENDOR_SONY].start = sony_start;
  595.     scsipt_vutbl[VENDOR_SONY].halt = NULL;
  596. }
  597.  
  598.  
  599. /*
  600.  * sony_start
  601.  *    Start the vendor-unique support module.  In the case of the Sony,
  602.  *    we want to set the drive's CD addressing to MSF mode.  Some Sony
  603.  *    drives use the Mode Select command (page 0x8) to do this while
  604.  *    others use a special vendor-unique "Set Address Format" command.
  605.  *    We determine which to use by overloading the meaning of the
  606.  *    app_data.msen_dbd configuration parameter.
  607.  *
  608.  * Args:
  609.  *    Nothing.
  610.  *
  611.  * Return:
  612.  *    Nothing.
  613.  */
  614. void
  615. sony_start(void)
  616. {
  617.     byte_t            buf[SZ_VS_CDPARM];
  618.     mode_sense_data_t    *ms_data;
  619.     blk_desc_t        *bdesc;
  620.     cdparm_pg_t        *parm_pg;
  621.  
  622.     if (app_data.msen_dbd) {
  623.         /* Send "Set Address Format" command */
  624.         pthru_send(OP_VS_SETADDRFMT,
  625.                0, NULL, 0, 0, 1, 0, 0, READ_OP, TRUE);
  626.     }
  627.     else {
  628.         /* Do Mode Sense command, CD-ROM parameters page */
  629.         if (!pthru_send(OP_S_MSENSE, (word32_t) (PG_VS_CDPARM << 8),
  630.                 buf, SZ_VS_CDPARM, 0, SZ_VS_CDPARM,
  631.                 0, 0, READ_OP, TRUE))
  632.             return;        /* Error */
  633.  
  634.         DBGDUMP("Mode Sense data bytes", buf, SZ_VS_CDPARM);
  635.  
  636.         ms_data = (mode_sense_data_t *)(void *) buf;
  637.         bdesc = (blk_desc_t *)(void *) ms_data->data;
  638.         parm_pg = (cdparm_pg_t *)(void *)
  639.               &ms_data->data[ms_data->bdescr_len];
  640.  
  641.         if (parm_pg->pg_code != PG_VS_CDPARM)
  642.             return;        /* Error */
  643.  
  644.         ms_data->data_len = 0;
  645.         if (ms_data->bdescr_len > 0)
  646.             bdesc->num_blks = 0;
  647.  
  648.         /* Set the drive up for MSF address mode */
  649.         parm_pg->lbamsf = 1;
  650.  
  651.         DBGDUMP("Mode Select data bytes", buf, SZ_VS_CDPARM);
  652.  
  653.         /* Do Mode Select command, CD-ROM parameters page */
  654.         pthru_send(
  655.             OP_S_MSELECT, 0, buf, SZ_VS_CDPARM, 0,
  656.             SZ_VS_CDPARM, 0x10, 0, WRITE_OP, TRUE
  657.         );
  658.     }
  659. }
  660.  
  661.  
  662. #endif    /* VENDOR_SONY */
  663.  
  664.